package serial_cli

import (
	"encoding/hex"
	"fmt"
	"github.com/spf13/cobra"
	"go.bug.st/serial"
	"log"
	"strings"
	"time"
)

var sendData *string
var waitingTime *uint32
var sendRedo *uint8

func SendCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "send",
		Short: "对串口发送报文",
		Long:  `对串口发送报文 如 send -d "01 ff 0a"`,
		//Args: func(cmd *cobra.Command, args []string) error {
		//	if len(args) < 1 {
		//		return errors.New("requires a data argument")
		//	}
		//	return nil
		//},
		Run: sendCmdRun,
	}
	sendData = cmd.Flags().StringP("data", "d", "01", "发送的报文默认 01")
	waitingTime = cmd.Flags().Uint32P("sleep", "s", 1000, "发送之后等久去获取报文")
	sendRedo = cmd.Flags().Uint8P("redo", "r", 1, "重次次数")
	return cmd
}

func sendCmdRun(cmd *cobra.Command, args []string) {
	serialConfig := loadConfig()
	parity := serial.NoParity

	switch serialConfig.Parity {
	case "N":
		parity = serial.NoParity
	case "O":
		parity = serial.OddParity
	case "E":
		parity = serial.EvenParity
	case "S":
		parity = serial.SpaceParity
	case "M":
		parity = serial.MarkParity
	default:
		parity = serial.NoParity
	}

	stopBits := serial.OneStopBit

	switch serialConfig.StopBits {
	case 1:
		stopBits = serial.OneStopBit
	case 2:
		stopBits = serial.TwoStopBits
	case 15:
		stopBits = serial.OnePointFiveStopBits
	default:
		stopBits = serial.OneStopBit
	}

	mode := &serial.Mode{
		BaudRate: int(serialConfig.BaudRate),
		Parity:   parity,
		DataBits: int(serialConfig.DataBits),
		StopBits: stopBits,
	}

	//打开串口
	port, err := serial.Open(serialConfig.Name, mode)

	if serialConfig.ReadTimeout > 0 {
		err := port.SetReadTimeout(time.Millisecond * time.Duration(serialConfig.ReadTimeout))
		if err != nil {
			log.Printf("SetReadTimeout error ", err)
			err = nil
		}
	}

	//关闭串口
	defer func() {
		if port != nil {
			_ = port.Close()
		}
	}()

	if err != nil {
		log.Fatal("串口打开失败 ", err)
	}

	fmt.Printf("[串口] %+v \n\n", port)

	bytes, err := hex.DecodeString(strings.ReplaceAll(*sendData, " ", ""))
	//bytes, err = hex.DecodeString(strings.ReplaceAll(*sendData, "0x", ""))
	if err != nil {
		log.Fatal("报文异常 ", err)
	}

	for i := 0; i < int(*sendRedo); i++ {
		fmt.Printf("[发送] % x \n", bytes)

		_, err = port.Write(bytes)
		if err != nil {
			log.Fatal(err)
		}

		fmt.Printf("[等侍] %d ms \n", *waitingTime)
		time.Sleep(time.Millisecond * time.Duration(*waitingTime))

		buff := make([]byte, 10000)

		// Reads up to 100 bytes
		n, err := port.Read(buff)
		if err != nil {
			log.Fatal(err)
		}

		if n == 0 {
			fmt.Println("没有报文返回!!!")
			return
		}

		fmt.Printf("[回复] % x \n", string(buff[:n]))
		fmt.Println("\n")
	}

}
